/*******************************************************************************
StringKit.cpp

	Author:		LiuDingXi
	e-mail:		liudx@gmail.com
	Date time:	2009-08-07

	Copyright (C) 2009
	All rights reserved.
	
*******************************************************************************/
#include "StdAfx.h"
#include "StringKit.h"
#include "SceneKit.h"


CStringKit::CStringKit()
{
	m_pHead = m_pTail = NULL;
}

CStringKit::~CStringKit()
{
	Free();
}

BOOL CStringKit::Load(CArchive& ar)
{
	if(m_szName.IsEmpty())
	{
		TCHAR szPath[MAX_PATH];
		 _tcscpy(szPath, ar.GetFile()->GetFilePath());
		 LPTSTR pTail = PathFindFileName(szPath);
		 if(pTail)
		 {
			LPCTSTR p = pTail;		 
			while(*p && *p != _T('.'))
			{
				m_szName += *p++;
			}
			 *pTail = 0;
		 }
	}

	CString s;
	while(ar.ReadString(s))
	{
		if(!s.IsEmpty())
		{
			SNODE* pNode = new SNODE;
			if(m_pHead == NULL)
			{
				m_pHead = pNode;
				m_pTail = pNode;
			}
			else
			{
				m_pTail->pNext = pNode;
				m_pTail = pNode;
			}
			
			int nIndex = eID;

			LPCTSTR p = s;
			while(*p)
			{
				if(*p == _T('\t') || *p == _T(' '))
				{
					if(pNode->szField[nIndex].GetLength() > 0)
						nIndex++;
				}
				else if(nIndex < eCount)
				{
					pNode->szField[nIndex] += *p;
					if(IsDBCSLeadByte(*p))
					{
						p++;
						pNode->szField[nIndex] += *p;
					}
				}
				p++;
			}
		}
	}
	return TRUE;
}

BOOL CStringKit::Store(CArchive& ar)
{
	const SNODE* pNode = m_pHead;
	while(pNode)
	{
		CString s;
		for(int i=0; i<eCount; i++)
		{
			if(pNode->szField[i].IsEmpty())
				break;
			s += pNode->szField[i];
			s += "\t";
		}
		s += "\r\n";
		ar.WriteString(s);
		
		pNode = pNode->pNext;
	}

	return TRUE;
}

BOOL CStringKit::Free()
{
	// release nodes
	while(m_pHead)
	{
		SNODE* pDel = m_pHead;
		m_pHead = m_pHead->pNext;
		delete pDel;
	}
	m_pTail = NULL;

	return TRUE;
}


static inline BYTE Hex(TCHAR c)
{
	if(c >= '0' && c <= '9')
	{
		return (c - '0');
	}
	else if(c >= 'A' && c <= 'F')
	{
		return (c - 'A');
	}
	else if(c >= 'a' && c <= 'f')
	{
		return (c - 'a');
	}
	return 0;
}

static COLORREF StrColor(const CString& s)
{
	if(s == "red")
	{
		return RGB(255, 0, 0);
	}
	else if(s == "blue")
	{
		return RGB(0, 0, 255);
	}
	else if(s == "green")
	{
		return RGB(0, 255, 0);
	}
	else if(s[0] == '#')
	{
		if(s.GetLength() == 4)
		{
			BYTE r = Hex(s[1]);
			BYTE g = Hex(s[2]);
			BYTE b = Hex(s[3]);
			return RGB(r, g, b);
		}
		else if(s.GetLength() == 7)
		{
			BYTE r = ( Hex(s[1]) << 4 ) + Hex(s[2]);
			BYTE g = ( Hex(s[3]) << 4 ) + Hex(s[4]);
			BYTE b = ( Hex(s[5]) << 4 ) + Hex(s[6]);
			return RGB(r, g, b);
		}
	}
	return atol(s);
}

SINT CStringKit::SaveDat(LPCTSTR szOutput)
{
	if(m_pHead != NULL)
	{
		HFONT hFont;
		LOGFONT lFont;
		memset(&lFont, 0, sizeof(lFont));
		_tcscpy(lFont.lfFaceName, _T("system"));
		lFont.lfHeight=16;
		lFont.lfWeight=0;
		lFont.lfItalic=false;
		lFont.lfUnderline=false;
		lFont.lfCharSet = DEFAULT_CHARSET;
		hFont = ::CreateFontIndirect(&lFont);

		COLORREF cText = RGB(255, 255, 255);

		SNODE* pNode = m_pHead;
		while(pNode)
		{
			pNode->pImage = new IMAGE;

			if(!pNode->szField[eColor].IsEmpty())
			{
				cText = StrColor(pNode->szField[eColor]);
			}

			bool bChanged = false;
			if(!pNode->szField[eFont].IsEmpty())
			{
				_tcscpy(lFont.lfFaceName, pNode->szField[eFont]);
				bChanged = true;
			}

			if(!pNode->szField[eSize].IsEmpty())
			{
				lFont.lfHeight = atol(pNode->szField[eSize]);
				bChanged = true;
			}
			if(!pNode->szField[eBold].IsEmpty())
			{
				lFont.lfWeight = atol(pNode->szField[eBold]);
				bChanged = true;
			}
			if(!pNode->szField[eItalic].IsEmpty())
			{
				lFont.lfItalic = atoi(pNode->szField[eItalic]);
				bChanged = true;
			}
			if(!pNode->szField[eUnderline].IsEmpty())
			{
				lFont.lfUnderline = atoi(pNode->szField[eUnderline]);
				bChanged = true;
			}

			if(bChanged)
			{
				::DeleteObject(hFont);

				hFont = ::CreateFontIndirect(&lFont);
			}
			
			pNode->pImage->xImage.Create(NULL, pNode->szField[eText], 
				pNode->szField[eText].GetLength(), 
				hFont, cText, RGB(0, 0, 0), true);

			pNode->pImage->x = 0;
			pNode->pImage->y = 0;
			pNode->pImage->cx = pNode->pImage->xImage.GetWidth();
			pNode->pImage->cy = pNode->pImage->xImage.GetHeight();

			pNode = pNode->pNext;
		}
		::DeleteObject(hFont);

		typedef CSightKit::SIMG SIMG;

		list<SIMG> ImgList;

		pNode = m_pHead;
		while(pNode)
		{
			SIMG sImg(pNode->pImage);

			ImgList.push_back(sImg);

			pNode = pNode->pNext;
		}

		SINT nImages = CSightKit::SaveImages(ImgList, szOutput+m_szName);

		CString szDatFile(szOutput);
		szDatFile += m_szName + _T(".srs");


		CCoder Coder;
		Coder.SetFolder(szOutput);

		CString szDefFile = Coder.m_szSrcFolder;
		szDefFile += m_szName + _T(".h");
		
		if(!PathFileExists(szDefFile))
		{
			CString szTplFile = Coder.m_szTplFolder;
			szTplFile += _T("string.h");
			Coder.TemplateOf(szTplFile, szDefFile, _T("NameX"), m_szName);
		}

		Coder.Load(m_szName + _T(".h"));

		CString szEnum(_T("\tenum {\r\n"));

		int nCount = 0;

		pNode = m_pHead;
		while(pNode)
		{
			szEnum += _T("\t");
			szEnum += pNode->szField[eID];
			szEnum += _T(",\r\n");

			nCount++;

			pNode = pNode->pNext;
		}

		szEnum += _T("\t};\r\n");

		Coder.LnRemove(_T("STRING_ENUM_BEGIN"), _T("STRING_ENUM_END"));
		Coder.LnInsert(_T("STRING_ENUM_BEGIN"), szEnum);

		Coder.Save(m_szName + _T(".h"));

		try
		{
			CFile file(szDatFile, CFile::modeCreate|CFile::modeWrite);

			SceneDat::STRS Head;
			Head.nFiles = nImages;
			Head.nImg = nCount;

			pNode = m_pHead;
			if(pNode)
			{
				Head.pImg[0].x = pNode->pImage->x;
				Head.pImg[0].y = pNode->pImage->y;
				Head.pImg[0].cx = pNode->pImage->cx;
				Head.pImg[0].cy = pNode->pImage->cy;
				Head.pImg[0].nType = SceneDat::eImage;
				Head.pImg[0].nIdx = pNode->pImage->idx;

				pNode = pNode->pNext;
			}

			file.Write(&Head, sizeof(Head));

			while(pNode)
			{
				SceneDat::IMG img;
				img.x = pNode->pImage->x;
				img.y = pNode->pImage->y;
				img.cx = pNode->pImage->cx;
				img.cy = pNode->pImage->cy;
				img.nType = SceneDat::eImage;
				img.nIdx = pNode->pImage->idx;

				file.Write(&img, sizeof(img));

				pNode = pNode->pNext;
			}
			file.Close();

			return TRUE;
		}
		catch(CException* e)
		{
			e->ReportError();
			e->Delete();
		}
	}
	return FALSE;
}
